#include "Xml.h"
#include <iostream>
#include <sstream>
using namespace std;

CXml::CXml(void):m_root(0), m_time(0)
{
	m_nodeRoot=new Separator();
}

CXml::~CXml(void){}

bool CXml::open(string filename)
{
	if ( !m_xmlFile.Read( filename.c_str() ))
	{
		cerr << "Failed to read xml file" << endl;
		return false;
	}
	m_root= new Element(m_xmlFile.RootElement());
	stringstream ss;
	ss.str(m_root->Attribute("windowWidth"));
	ss>>m_windowWidth;
	ss.clear();
	ss.str(m_root->Attribute("windowHeight"));
	ss>>m_windowHeight;
	return true;
}

bool CXml::read(Group* root, Element* element)
{
	//get the list of element
	list<Element> listOfElement;
	if(element==0)
		listOfElement= m_root->Children();
	else
		listOfElement=element->Children();

	//go through the list
	for(list<Element>::iterator i=listOfElement.begin(); i!=listOfElement.end(); i++)
	{
		Element node =(*i);
		switch(CXml::convertNameToInt(&node))
		{
			case CXml::eTypeCamera:
				addCamera(&node, root);
				break;
			case CXml::eTypeLookAt:
				addLookAt(&node, root);
				break;
			case CXml::eTypeBezier3Curve:
				addBezier3Curve(&node, root);
				break;
			case CXml::eTypeApplicationTime:
				addApplicationTime(&node, root);
				break;
			case CXml::eTypeBezierPath:
				addBezierPath(&node, root);
				break;
			case CXml::eTypeParticleSystem:
				addParticleSystem(&node, root);
				break;
			case CXml::eTypeSeparator:
				if(!addSeparator(&node, root))
					return false;
				break;
			case CXml::eTypeMaterial:
				addMaterial(&node, root);
				break;
			case CXml::eTypeCube:
				if(!addCube(&node, root))
					return false;
				break;
			case CXml::eTypeTranslate:
				addTranslate(&node, root);
				break;
			case CXml::eTypeRotate:
				addRotate(&node, root);
				break;
			case CXml::eTypeTimeController:
				addTimeController(&node);
				break;
			case CXml::eTypeLinearFunction:
				addLinearFunction(&node);
				break;
			case CXml::eTypeConstantFloat:
				addConstantFloat(&node);
				break;
			case CXml::eTypePutInVector3:
				addPutInVector3(&node);
				break;
			case CXml::eTypeKinetic:
				addKinetic(&node, root);
				break;
			case CXml::eTypeKeyframe:
				addKeyframe(&node);
				break;
			case CXml::eTypeBezierCoordinates:
				addBezierCoordinates(&node, root);
				break;
			case CXml::eTypeCosinus:
				addCosinus(&node);
				break;
			case CXml::eTypeSinus:
				addSinus(&node);
				break;
			case CXml::eTypeTerrain:
				addTerrain(&node, root);
				break;
			case CXml::eTypeCanon:
				addCanon(&node, root);
				break;
			case CXml::eTypeAwesomeAttraction:
				addAwesomeAttraction(&node, root);
				break;
			//case CXml::eTypeLight:
			//	addLight(&node, root);
			//	break;
			case CXml::eTypePillar:
				addPillar(&node, root);
				break;
			case CXml::eTypeGreatWheel:
				addGreatWheel(&node, root);
				break;
			case CXml::eTypeCarousel:
				addCarousel(&node, root);
			case CXml::eTypeUnknown:
				break;
		}
	}
	return true;
}

bool CXml::addCamera(Element* node, Group* root)
{
	if( node->Name()!="camera")
	{
		return false;
	}
	else
	{
		stringstream ss;
		string temp;
		//get the ratio in string
		string sRatio=node->Attribute("ratio");
		//get the index of the /
		int indexSeparator=sRatio.find("/");
		//get the first part of the ratio in string then convert it into float
		string sFirstPartRatio=sRatio.substr(0,indexSeparator);
		float fFirstPartRatio=atof(sFirstPartRatio.c_str());
		

		//get the second part of the ratio in string then convert it into a float
		string sSecondPartRatio=sRatio.substr(indexSeparator+1,sRatio.length());
		float fSecondPartRatio=atof(sSecondPartRatio.c_str());
		

		//get the field of view
		temp=node->Attribute("fov");
		ss.str(temp);
		float fFov;
		ss>>fFov;

		//get the near distance
		temp=node->Attribute("near");
		ss.clear();
		ss.str(temp);
		float fNear;
		ss>>fNear;

		//get the far distance
		temp=node->Attribute("far");
		ss.clear();
		ss.str(temp);
		float fFar; 
		ss>>fFar;

		//debug info
	#ifdef XML_DEBUG_CAMERA
		cout<<"firstPartRatio="<<fFirstPartRatio<<endl;
		cout<<"secondPartRatio="<<fSecondPartRatio<<endl;
		cout<<"fov="<<fFov<<endl;
		cout<<"near="<<fNear<<endl;
		cout<<"far="<<fFar<<endl;
	#endif

		//create the camera and add to the root
		Camera* camera= new Camera(fFirstPartRatio/fSecondPartRatio,fFov, fNear, fFar);
		root->addChild(camera);
		return true;
	}
}

bool CXml::addLookAt(Element* node, Group* root)
{
	if(node->Name()!="lookAt")
		return false;
	
	LookAt* lookat= new LookAt();

	//create a list of element and put all the children in that list
	list<Element> listElements=node->Children();
	
	list<Element>::iterator i=listElements.begin();
	stringstream ss;
	if((*i).Attribute("connectFrom")=="0")
	{
		Vector3 position;
		ss.str((*i).Attribute("x"));
		ss>>position.x;
		ss.clear();
		ss.str((*i).Attribute("y"));
		ss>>position.y;
		ss.clear();
		ss.str((*i).Attribute("z"));
		ss>>position.z;
		ss.clear();
		
		lookat->eye=position;
	}
	else
	{
		void* controller=getController((*i).Attribute("connectFrom"));
		lookat->eye.connectFrom((tsg::Source<Vector3>*)controller);
	}
	i++;
	if((*i).Attribute("connectFrom")=="0")
	{
		Vector3 at;
		ss.str((*i).Attribute("x"));
		ss>>at.x;
		ss.clear();
		ss.str((*i).Attribute("y"));
		ss>>at.y;
		ss.clear();
		ss.str((*i).Attribute("z"));
		ss>>at.z;
		ss.clear();
		
		lookat->at=at;
	}
	else
	{
		void* controller=getController((*i).Attribute("connectFrom"));
		lookat->at.connectFrom((tsg::Source<Vector3>*)controller);
	}
	i++;
	if((*i).Attribute("connectFrom")=="0")
	{
		Vector3 up;
		ss.str((*i).Attribute("x"));
		ss>>up.x;
		ss.clear();
		ss.str((*i).Attribute("y"));
		ss>>up.y;
		ss.clear();
		ss.str((*i).Attribute("z"));
		ss>>up.z;
		ss.clear();
		
		lookat->up=up;
	}
	else
	{
		void* controller=getController((*i).Attribute("connectFrom"));
		lookat->up.connectFrom((tsg::Source<Vector3>*)controller);
	}
	
	

			//debug info
		#ifdef XML_DEBUG_LOOKAT
			cout<<"LOOKAT"<<endl;
			cout<<" position x="<<propertiesLookAt[0].x<<endl;
			cout<<" position y="<<propertiesLookAt[0].y<<endl;
			cout<<" position z="<<propertiesLookAt[0].z<<endl<<endl;

			cout<<" at x="<<propertiesLookAt[1].x<<endl;
			cout<<" at y="<<propertiesLookAt[1].y<<endl;
			cout<<" at z="<<propertiesLookAt[1].z<<endl<<endl;

			cout<<" up x="<<propertiesLookAt[2].x<<endl;
			cout<<" up x="<<propertiesLookAt[2].y<<endl;
			cout<<" up x="<<propertiesLookAt[2].z<<endl<<endl;
		#endif

			//create the lookat and add it to the root
		root->addChild(lookat);


		return true;
	
}

bool CXml::addBezier3Curve(Element* node, Group* root)
{
	if(node->Name()!="bezier3Curve")
	{
		return false;
	}
	else
	{
		//get all the path
		list<Element> listOfPoints=node->Children();
		Vector3 points[4];
		int j=0;
		//for one path i get the 4 controller points
		for(list<Element>::iterator i=listOfPoints.begin(); i!=listOfPoints.end(); i++)
		{
			Element currentPoint=*i;
			stringstream ss;
			ss.str(currentPoint.Attribute("x"));
			ss>>points[j].x;

			ss.clear();
			ss.str(currentPoint.Attribute("y"));
			ss>>points[j].y;

			ss.clear();
			ss.str(currentPoint.Attribute("z"));
			ss>>points[j].z;

			j++;
		}
		Bezier3Curve* bezierCurve=new Bezier3Curve();
		bezierCurve->controlPoints.push_back(points[0]);
		bezierCurve->controlPoints.push_back(points[1]);
		bezierCurve->controlPoints.push_back(points[2]);
		bezierCurve->controlPoints.push_back(points[3]);
		root->addChild(bezierCurve);

		#ifdef XML_DEBUG_BEZIER3CURVE
				cout<<"BEZIER3CURVE"<<endl;
				cout<<" controller point 1 x="<<points[0].x<<endl;
				cout<<" controller point 1 y="<<points[0].y<<endl;
				cout<<" controller point 1 z="<<points[0].z<<endl<<endl;
				cout<<" controller point 2 x="<<points[1].x<<endl;
				cout<<" controller point 2 y="<<points[1].y<<endl;
				cout<<" controller point 2 z="<<points[1].z<<endl<<endl;
				cout<<" controller point 3 x="<<points[2].x<<endl;
				cout<<" controller point 3 y="<<points[2].y<<endl;
				cout<<" controller point 3 z="<<points[2].z<<endl<<endl;
				cout<<" controller point 4 x="<<points[3].x<<endl;
				cout<<" controller point 4 y="<<points[3].y<<endl;
				cout<<" controller point 4 z="<<points[3].z<<endl<<endl;
		#endif

		return true;
	}
}

bool CXml::addBezierPath(Element* node, Group* root)
{
	if(node->Name()!="bezierPath")
	{
		return false;
	}
	else
	{
		//get all the path
		bezierPath* bezier=new bezierPath();
		if(node->Attribute("loop")=="true")
			bezier->m_loop=true;
		else
			bezier->m_loop=false;

		list<Element> listOfPath=node->Children();
		
		//debug info
		#ifdef XML_DEBUG_BEZIERPATH
			int indexOfPath=0;
		#endif

		//for every path
		for(list<Element>::iterator i=listOfPath.begin(); i!=listOfPath.end(); i++)
		{

			//debug info
			#ifdef XML_DEBUG_BEZIERPATH
				cout<<"PATH NUMBER "<<indexOfPath<<endl;
			#endif

			Element currentPath=*i;
			//i get all the controller point
			list<Element> controllerPoint=currentPath.Children();
			Vector3 points[4];
			float time[4];
			int j=0;
			//for every controller point
			for(list<Element>::iterator k=controllerPoint.begin(); k!=controllerPoint.end(); k++)
			{
				Element currentControllerPoint=*k;
				stringstream ss;
				ss.str(currentControllerPoint.Attribute("x"));
				float x;
				ss>>x;

				ss.clear();
				ss.str(currentControllerPoint.Attribute("y"));
				float y;
				ss>>y;

				ss.clear();
				ss.str(currentControllerPoint.Attribute("z"));
				float z;
				ss>>z;

				ss.clear();
				ss.str(currentControllerPoint.Attribute("t"));
				float t;
				ss>>t;

				points[j].x=x;
				points[j].y=y;
				points[j].z=z;
				time[j]=t;
				j++;

				//debug info
				#ifdef XML_DEBUG_BEZIERPATH
					cout<<"BEZIER PATH"<<endl;
					cout<<" controller point "<<j<<" x="<<points[j].x<<endl;
					cout<<" controller point "<<j<<" y="<<points[j].y<<endl;
					cout<<" controller point "<<j<<" z="<<points[j].z<<endl;
					cout<<" controller point "<<j<<" t="<<t<<endl<<endl;
				#endif
			}
			bezier->addControllerPoint(points[0],time[0], points[1],time[1], points[2],time[2], points[3],time[3]);

			//debug info
			#ifdef XML_DEBUG_BEZIERPATH
				indexOfPath++;
			#endif
		}

		bezier->time.connectFrom(m_time);
		//bezier->m_loop=true;
		//add the frenet controller
		frenet*  frenetController = new frenet();
		frenetController->vectorPosition.connectFrom(&bezier->position);
		frenetController->vectorFirstDerivative.connectFrom(&bezier->firstDerivative);
		frenetController->vectorSecondDerivative.connectFrom(&bezier->secondDerivative);

		/*if(node->Attribute("name")=="0")
		{*/
			//plug the frenet controller in a transformation node
			Transformation* trans=new Transformation();
			trans->matrix.connectFrom(frenetController);

			root->addChild(trans);
		/*}
		else
		{
			registerController(node, frenetController);
		}*/
		return true;
	}
}

bool CXml::addApplicationTime(Element* node, Group* root)
{
	if(node->Name()!="applicationTime")
	{
		return false;
	}
	else
	{
		m_time = new ApplicationTime();
		return true;
	}
}

bool CXml::addParticleSystem(Element* node, Group* root)
{
	if(node->Name()!="particleSystem") 
		return false;

	//create the particle system
	stringstream ss;
	ss.str(node->Attribute("numberOfParticle"));
	int numberOfParticles;
	ss>>numberOfParticles;
	CParticleSystem* particleSystem = new CParticleSystem(numberOfParticles);

	//give the euler step and connect to the time
	ss.clear();
	ss.str(node->Attribute("eulerStep"));
	float x;
	ss>>x;
	particleSystem->m_eulerStep=x;
	particleSystem->m_time.connectFrom(m_time);

	//get the emitter, simulation and reaper
	list<Element> children=node->Children();
	for(list<Element>::iterator i=children.begin(); i!=children.end(); i++)
	{
		if((*i).Name()=="emitter")
		{
			//get all the children and the number of particle to emit
			list<Element> emitter=(*i).Children();
			ss.clear();
			ss.str((*i).Attribute("numberOfParticleToEmit"));
			int numberOfParticleToEmit;
			ss>>numberOfParticleToEmit;
			int y, z;
			if((*i).Attribute("type")=="pointEmitter")
			{
				CPointEmitter* pointEmitter = new CPointEmitter();
				list<Element>::iterator j=emitter.begin();
				if(j->Attribute("connectFrom")=="0")
				{
					Vector3 velocity;
					float temp;
					ss.clear();
					ss.str((*j).Attribute("x"));
					ss>>temp;
					velocity.x=temp;
					ss.clear();
					ss.str((*j).Attribute("y"));
					ss>>temp;
					velocity.y=temp;
					ss.clear();
					ss.str((*j).Attribute("z"));
					ss>>temp;
					velocity.z=temp;
					pointEmitter->m_velocity=velocity;
				}
				else
				{
					void* controller=getController(j->Attribute("connectFrom"));
					if(controller==0)
					{
						delete pointEmitter;
						return false;
					}
					pointEmitter->m_velocity.connectFrom((tsg::Source<Vector3>*)controller);
				}
				j++;
				ss.clear();
				ss.str((*j).Attribute("x"));
				ss>>x;

				ss.clear();
				ss.str((*j).Attribute("y"));
				ss>>y;

				ss.clear();
				ss.str((*j).Attribute("z"));
				ss>>z;

				
				pointEmitter->m_numberOfParticleToEmit=numberOfParticleToEmit;
				pointEmitter->m_position=Vector3(x, y, z);

				//plug the emitter and the particle system
				particleSystem->m_pointerEmitter=pointEmitter;
				pointEmitter->m_particleSystem=particleSystem;
				
			}
			else if((*i).Attribute("type")=="circleEmitter")
			{
				CCircleEmitter* circleEmitter = new CCircleEmitter();
				list<Element>::iterator j=emitter.begin();
				if(j->Attribute("connectFrom")=="0")
				{
					Vector3 velocity;
					float temp;
					ss.clear();
					ss.str((*j).Attribute("x"));
					ss>>temp;
					velocity.x=temp;
					ss.clear();
					ss.str((*j).Attribute("y"));
					ss>>temp;
					velocity.y=temp;
					ss.clear();
					ss.str((*j).Attribute("z"));
					ss>>temp;
					velocity.z=temp;
					circleEmitter->m_velocity=velocity;
				}
				else
				{
					void* controller=getController(j->Attribute("connectFrom"));
					if(controller==0)
					{
						delete circleEmitter;
						return false;
					}
					circleEmitter->m_velocity.connectFrom((tsg::Source<Vector3>*)controller);
				}
				j++;
				ss.clear();
				ss.str((*j).Attribute("x"));
				ss>>x;

				ss.clear();
				ss.str((*j).Attribute("y"));
				ss>>y;

				ss.clear();
				ss.str((*j).Attribute("z"));
				ss>>z;

				int radius;
				ss.clear();
				j++;
				ss.str((*j).Content());
				ss>>radius;

				
				circleEmitter->m_numberOfParticleToEmit=numberOfParticleToEmit;
				circleEmitter->m_position=Vector3(x, y, z);
				circleEmitter->m_radius=radius;

				//plug the emitter and the particle system
				particleSystem->m_pointerEmitter=circleEmitter;
				circleEmitter->m_particleSystem=particleSystem;

			}
			else if((*i).Attribute("type")=="fullSquareEmitter")
			{
				CFullSquareEmitter* fullSquareEmitter = new CFullSquareEmitter();
				list<Element>::iterator j=emitter.begin();
				if(j->Attribute("connectFrom")=="0")
				{
					Vector3 velocity;
					float temp;
					ss.clear();
					ss.str((*j).Attribute("x"));
					ss>>temp;
					velocity.x=temp;
					ss.clear();
					ss.str((*j).Attribute("y"));
					ss>>temp;
					velocity.y=temp;
					ss.clear();
					ss.str((*j).Attribute("z"));
					ss>>temp;
					velocity.z=temp;
					fullSquareEmitter->m_velocity=velocity;
				}
				else
				{
					void* controller=getController(j->Attribute("connectFrom"));
					if(controller==0)
					{
						delete fullSquareEmitter;
						return false;
					}
					fullSquareEmitter->m_velocity.connectFrom((tsg::Source<Vector3>*)controller);
				}
				j++;
				ss.clear();
				ss.str((*j).Attribute("x"));
				ss>>x;

				ss.clear();
				ss.str((*j).Attribute("y"));
				ss>>y;

				ss.clear();
				ss.str((*j).Attribute("z"));
				ss>>z;

				int size;
				ss.clear();
				j++;
				ss.str((*j).Content());
				ss>>size;

				
				fullSquareEmitter->m_numberOfParticleToEmit=numberOfParticleToEmit;
				fullSquareEmitter->m_position=Vector3(x, y, z);
				fullSquareEmitter->m_size=size;

				//plug the emitter and the particle system
				particleSystem->m_pointerEmitter=fullSquareEmitter;
				fullSquareEmitter->m_particleSystem=particleSystem;
			}
			else if(i->Attribute("type")=="directionalPointEmitter")
			{
				list<Element>::iterator j=emitter.begin();
				CDirectionalPointEmitter* newEmitter = new CDirectionalPointEmitter();
				if(j->Attribute("connectFrom")=="0")
				{
					Vector3 velocity;
					float temp;
					ss.clear();
					ss.str((*j).Attribute("x"));
					ss>>temp;
					velocity.x=temp;
					ss.clear();
					ss.str((*j).Attribute("y"));
					ss>>temp;
					velocity.y=temp;
					ss.clear();
					ss.str((*j).Attribute("z"));
					ss>>temp;
					velocity.z=temp;
					newEmitter->m_velocity=velocity;
				}
				else
				{
					void* controller=getController(j->Attribute("connectFrom"));
					if(controller==0)
					{
						delete newEmitter;
						return false;
					}
					newEmitter->m_velocity.connectFrom((tsg::Source<Vector3>*)controller);
				}
				j++;
				if(j->Attribute("connectFrom")=="0")
				{
					Vector3 position;
					float temp;
					ss.clear();
					ss.str((*j).Attribute("x"));
					ss>>temp;
					position.x=temp;

					ss.clear();
					ss.str((*j).Attribute("y"));
					ss>>temp;
					position.y=temp;

					ss.clear();
					ss.str((*j).Attribute("z"));
					ss>>temp;
					position.z=temp;
					newEmitter->m_position=position;
				}
				else
				{
					void* controller = getController(j->Attribute("connectFrom"));
					if(controller==0)
					{
						delete newEmitter;
						return false;
					}
					newEmitter->m_position.connectFrom((tsg::Source<Vector3>*)controller); 
				}
				j++;
				if(j->Attribute("connectFrom")=="0")
				{
					Vector3 direction;
					float temp;
					ss.clear();
					ss.str((*j).Attribute("x"));
					ss>>temp;
					direction.x=temp;

					ss.clear();
					ss.str((*j).Attribute("y"));
					ss>>temp;
					direction.y=temp;

					ss.clear();
					ss.str((*j).Attribute("z"));
					ss>>temp;
					direction.z=temp;
					newEmitter->m_direction=direction;
				}
				else
				{
					void* controller = getController(j->Attribute("connectFrom"));
					if(controller==0)
					{
						delete newEmitter;
						return false;
					}
					newEmitter->m_direction.connectFrom((tsg::Source<Vector3>*)controller); 
				}
				newEmitter->m_numberOfParticleToEmit=numberOfParticleToEmit;
				//plug the emitter and the particle system
				particleSystem->m_pointerEmitter=newEmitter;
				newEmitter->m_particleSystem=particleSystem;
			
			}
			else{return false;}
		}
		else if((*i).Name()=="simulation")
		{
			if((*i).Attribute("type")=="simpleSimulation")
			{
				CSimpleSimulation* simpleSimulation = new CSimpleSimulation();

				//plug the simulation and the particle system
				particleSystem->m_pointerSimulation=simpleSimulation;
				simpleSimulation->m_particleSystem=particleSystem;

			}
			else if((*i).Attribute("type")=="attractionSimulation")
			{
				CAttractionSimulation* newSimulation = new CAttractionSimulation();

				//plug the simulation and the particle system
				particleSystem->m_pointerSimulation=newSimulation;
				newSimulation->m_particleSystem=particleSystem;

			}
			else{return false;}
		}
		else if((*i).Name()=="reaper")
		{
			list<Element> reaper=(*i).Children();
			if((*i).Attribute("type")=="timeReaper")
			{
				list<Element>::iterator j=reaper.begin();
				ss.clear();
				ss.str((*j).Content());
				ss>>x;

				CTimeReaper* reaper = new CTimeReaper();
				reaper->m_lifeSpan=x;
				reaper->m_time.connectFrom(m_time);
				//plug the reaper and the particle system
				particleSystem->m_pointerReaper=reaper;
				reaper->m_particleSystem=particleSystem;
			}
			else{return false;}
		}
		else if(i->Name()=="display")
		{
			list<Element> display=(*i).Children();
			if((*i).Attribute("type")=="particlesPoint")
			{
				list<Element>::iterator j=display.begin();
				CParticles* drawParticles = new CParticles();


				float size;
				ss.clear();
				ss.str(j->Content());
				ss>>size;
				drawParticles->m_size=size;
		

				
				drawParticles->m_arrayOfParticles.connectFrom(particleSystem);
				drawParticles->m_numberOfParticles=numberOfParticles;
				root->addChild(drawParticles);
				return true;
			}
			else
				return false;
		}
	}
	return true;
}

bool CXml::addSeparator(Element* node, Group* root)
{
	//add the separator to the stack of root
	Group* separator = new Separator();
	root->addChild(separator);
	if(!read(separator, node))
		return false;

	return true;
}

bool CXml::addMaterial(Element* node, Group* root)
{
	if(node->Name()!="material")
		return false;

	list<Element> listColour=node->Children();
	list<Element>::iterator colour=listColour.begin();

	//get the ambiant colour
	float ambientColour[3];
	char* attributes[3] = {"r", "g", "b"};
	stringstream ss;
	for(int i=0; i<3; i++)
	{
		ss.str((*colour).Attribute(attributes[i]));
		ss>>ambientColour[i];
		ss.clear();
	}

	//get the diffuse colour
	float diffuseColour[3];
	colour++;
	for(int i=0; i<3; i++)
	{
		ss.str((*colour).Attribute(attributes[i]));
		ss>>diffuseColour[i];
		ss.clear();
	}

	//get the specular colour
	float specularColour[3];
	colour++;
	for(int i=0; i<3; i++)
	{
		ss.str((*colour).Attribute(attributes[i]));
		ss>>specularColour[i];
		ss.clear();
	}

	//get the shininess
	colour++;
	float shininess;
	ss.str((*colour).Content());
	ss>>shininess;

	//create the material
	Colour ambient(ambientColour[0], ambientColour[1], ambientColour[2]);
	Colour diffuse(diffuseColour[0], diffuseColour[1], diffuseColour[2]);
	Colour specular(specularColour[0], specularColour[1], specularColour[2]);
	Material* newMaterial = new Material(ambient, diffuse, specular, shininess);
	root->addChild(newMaterial);
	return true;
}

bool CXml::addCube(Element* node, Group* root)
{
	if(node->Name()!="cube")
		return false;

	Cube* newCube = new Cube();
	list<Element> size=node->Children();
	list<Element>::iterator i =size.begin();
	string connectFrom=(*i).Attribute("connectFrom");
	if(connectFrom=="0")
	{
		float size;
		stringstream ss;
		ss.str((*i).Content());
		ss>>size;
		newCube->size=size;
	}
	else
	{
		void* controller=getController(connectFrom);
		if(controller!=0)
			newCube->size.connectFrom((tsg::Source<float>*)controller);
		else
			return false;
	}


	root->addChild(newCube);
	return true;
}

bool CXml::addTranslate(Element* node, Group* root)
{
	if(node->Name()!="translate")
		return true;

	Translate* newTranslate = new Translate();
	if(node->Attribute("connectFrom")!="0")
	{
		void* controller=getController(node->Attribute("connectFrom"));
		if(controller!=0)
		{
			newTranslate->xyz.connectFrom((tsg::Source<tsg::Vector3>*)controller);
			root->addChild(newTranslate);
			return true;
		}
		return false;
	}
	char* attributes[3]={"x", "y", "z"};
	float coordinate[3];
	stringstream ss;
	for(int i=0; i<3; i++)
	{
		ss.str(node->Attribute(attributes[i]));
		ss>>coordinate[i];
		ss.clear();
	}

	newTranslate->xyz=Vector3(coordinate[0], coordinate[1], coordinate[2]);
	root->addChild(newTranslate);
	return true;
}

bool CXml::addRotate(Element* node, Group* root)
{
	if(node->Name()!="rotate")
		return false;

	Rotate* newRotate = new Rotate();
	stringstream ss;
	string axis=node->Attribute("axis");
	if(axis=="x" || axis=="X")
		newRotate->axis=Vector3(1, 0, 0);
	else if(axis=="y" || axis=="Y")
		newRotate->axis=Vector3(0, 1, 0);
	else if(axis=="z" || axis=="Z")
		newRotate->axis=Vector3(0, 0, 1);

	list<Element> angle = node->Children();
	list<Element>::iterator i=angle.begin();

	string connectFrom=(*i).Attribute("connectFrom");
	if(connectFrom!="0")
	{
		void* controller = getController(connectFrom);
		if(controller!=0)
			newRotate->angle.connectFrom((tsg::Source<float>*)controller);
		else
			return false;
	}
	else
	{
		ss.clear();
		ss.str((*i).Content());
		float valueOfAngle;
		ss>>valueOfAngle;
		newRotate->angle=valueOfAngle;
	}

	root->addChild(newRotate);
	return true;
}

bool CXml::addTimeController(Element* node)
{
	if(node->Name()!="timeController")
		return false;

	string name;
	stringstream ss;
	name=node->Attribute("name");
	float startTime;
	float endTime;

	ss.str(node->Attribute("startTime"));
	ss>>startTime;
	ss.clear();
	ss.str(node->Attribute("endTime"));
	ss>>endTime;

	CTimeController* newTimeController = new CTimeController();
	newTimeController->m_applicationTime.connectFrom(m_time);
	newTimeController->m_startTime=startTime;
	newTimeController->m_endTime=endTime;

	registerController(node, newTimeController);
	/*connectController newCC;
	newCC.m_nameOfController=name;
	newCC.m_pointerToController=newTimeController;
	m_vectorController.push_back(newCC);*/
	return true;

}

bool CXml::addLinearFunction(Element* node)
{
	if(node->Name()!="linearFunction")
		return false;

	stringstream ss;
	int coeff;
	int offset;
	CLinearFunction* newLinear = new CLinearFunction();

	connectController c;
	c.m_nameOfController=node->Attribute("name");
	c.m_pointerToController=newLinear;
	m_vectorController.push_back(c);

	ss.str(node->Attribute("coeff"));
	ss>>coeff;
	ss.clear();

	ss.str(node->Attribute("offset"));
	ss>>offset;


	newLinear->m_coeff=coeff;
	newLinear->m_offset=offset;

	if(node->Attribute("time")=="0")
		newLinear->m_time.connectFrom(m_time);
	else
	{
		void* controller=getController(node->Attribute("time"));
		newLinear->m_time.connectFrom((tsg::Source<float>*)controller);
	}
	return true;


}

bool CXml::addConstantFloat(Element *node)
{
	if(node->Name()!="constantFloat")
		return false;

	float defaultValue;
	float betweenTimeValue;

	CConstantFloat* newConstant = new CConstantFloat();
	registerController(node, newConstant);

	stringstream ss;
	ss.str(node->Attribute("defaultValue"));
	ss>>defaultValue;
	ss.clear();
	ss.str(node->Attribute("betweenTimeValue"));
	ss>>betweenTimeValue;

	newConstant->m_defaultValue=defaultValue;
	newConstant->m_betweenTimeValue=betweenTimeValue;
	if(node->Attribute("time")=="0")
		newConstant->m_time.connectFrom(m_time);
	else
	{
		void* controller=getController(node->Attribute("time"));
		if(controller!=0)
			newConstant->m_time.connectFrom((tsg::Controller<float>*)controller);
		else
			return false;
	}
	return true;
}

bool CXml::addPutInVector3(Element* node)
{
	if(node->Name()!="putInVector3")
		return false;

	CPutInVector3* newVector3 = new CPutInVector3();
	registerController(node, newVector3);

	list<Element> coordinate=node->Children();
	list<Element>::iterator i=coordinate.begin();

	stringstream ss;

	if((*i).Attribute("connectFrom")=="0")
	{
		ss.str((*i).Attribute("value"));
		float x;
		ss>>x;
		newVector3->m_x=x;
	}
	else
	{
		void* controller=getController((*i).Attribute("connectFrom"));
		if(controller!=0)
			newVector3->m_x.connectFrom((tsg::Source<float>*)controller);
		else
			return false;
	}
	i++;
	ss.clear();
	if((*i).Attribute("connectFrom")=="0")
	{
		ss.str((*i).Attribute("value"));
		float y;
		ss>>y;
		newVector3->m_y=y;
	}
	else
	{
		void* controller=getController((*i).Attribute("connectFrom"));
		if(controller!=0)
			newVector3->m_y.connectFrom((tsg::Source<float>*)controller);
		else
			return false;
	}
	i++;
	ss.clear();
	if((*i).Attribute("connectFrom")=="0")
	{
		ss.str((*i).Attribute("value"));
		float z;
		ss>>z;
		newVector3->m_z=z;
	}
	else
	{
		void* controller=getController((*i).Attribute("connectFrom"));
		if(controller!=0)
			newVector3->m_z.connectFrom((tsg::Source<float>*)controller);
		else
			return false;
	}
	return true;
}

bool CXml::addKinetic(Element* node, Group* root)
{
	if(node->Name()!="kinetic")
		return false;

	list<Element> kinetic=node->Children();
	list<Element>::iterator i=kinetic.begin();

	Vector3 position;
	stringstream ss;
	ss.str((*i).Attribute("x"));
	ss>>position.x;
	ss.clear();
	ss.str((*i).Attribute("y"));
	ss>>position.y;
	ss.clear();
	ss.str((*i).Attribute("z"));
	ss>>position.z;
	i++;
	Vector3 velocity;
	ss.clear();
	ss.str((*i).Attribute("x"));
	ss>>velocity.x;
	ss.clear();
	ss.str((*i).Attribute("y"));
	ss>>velocity.y;
	ss.clear();
	ss.str((*i).Attribute("z"));
	ss>>velocity.z;
	i++;
	float mass;
	ss.clear();
	ss.str((*i).Content());
	ss>>mass;
	CKineticMotion* newKinetic = new CKineticMotion();
	newKinetic->m_initialPosition=position;
	newKinetic->m_initialVelocity=velocity;
	newKinetic->m_mass=mass;
	i++;

	if((*i).Attribute("connectFrom")!="0")
	{
		void* controller=getController((*i).Attribute("connectFrom"));
		if(controller!=0)
			newKinetic->m_time.connectFrom((tsg::Source<float>*)controller);
		else
			return false;
	}
	else
		newKinetic->m_time.connectFrom(m_time);

	Translate* translate= new Translate();
	translate->xyz.connectFrom(newKinetic);

	root->addChild(translate);

	return true;
}

bool CXml::addKeyframe(Element* node)
{
	if(node->Name()!="keyframe")
		return false;

	CKeyframe* newKeyframe = new CKeyframe();
	registerController(node, newKeyframe);

	if(node->Attribute("easyinout")=="true")
		newKeyframe->easyinout=true;
	else
		newKeyframe->easyinout=false;

	list<Element> listStep=node->Children();

	for(list<Element>::iterator i=listStep.begin(); i!=listStep.end(); i++)
	{
		stringstream ss;
		ss.str((*i).Attribute("time"));
		float time;
		ss>>time;
		ss.clear();
		ss.str((*i).Attribute("position"));
		float position;
		ss>>position;

		newKeyframe->addKeyframe(new step(time, position));
	}
	newKeyframe->time.connectFrom(m_time);
	return true;
}

bool CXml::addBezierCoordinates(Element* node, Group* root)
{
	if(node->Name()!="bezierCoordinates")
		return false;

	int numberOfElement;
	stringstream ss;
	ss.str(node->Attribute("numberOfElementPerPath"));
	ss>>numberOfElement;
	CBezierCoordinate* newBezier = new CBezierCoordinate(numberOfElement);

	list<Element> path = node->Children();

	for(list<Element>::iterator i=path.begin(); i!=path.end(); i++) //for each path
	{
		list<Element> j=(*i).Children();//get the point

		for(list<Element>::iterator point=j.begin(); point!=j.end(); point++)
		{
			Vector3 bezierPoint;
			ss.clear();
			ss.str(point->Attribute("x"));
			ss>>bezierPoint.x;

			ss.clear();
			ss.str(point->Attribute("y"));
			ss>>bezierPoint.y;

			ss.clear();
			ss.str(point->Attribute("z"));
			ss>>bezierPoint.z;

			newBezier->m_vectorOfBezierPoint.push_back(bezierPoint);
		}	
	}

	newBezier->calculMatrix();

	if(node->Attribute("type")=="rail")
	{
		int size=newBezier->m_matrixRail.size();
		Group* rail=new Separator();
		for(int i=0; i<size; i++)
		{
			Transformation* newTransform = new Transformation(newBezier->m_matrixRail[i]);
			Group* newSeparator = new Separator();
			newSeparator->addChild(newTransform);
			newSeparator->addChild(new CRail(1));
			rail->addChild(newSeparator);
		}
		root->addChild(rail);
		return true;
	}
	else if(node->Attribute("type")=="rail2")
	{
		int size=newBezier->m_matrixRail.size();
		Group* rail=new Separator();
		for(int i=0; i<size; i++)
		{
			Transformation* newTransform = new Transformation(newBezier->m_matrixRail[i]);
			Group* newSeparator = new Separator();
			newSeparator->addChild(newTransform);
			newSeparator->addChild(new CRail2(1));
			rail->addChild(newSeparator);
		}
		root->addChild(rail);
		return true;
	
	}
	return false;
}

bool CXml::addCosinus(Element* node)
{
	if(node->Name()!="cosinus")
		return false;

	calculTrajectoryCos* newCos = new calculTrajectoryCos();
	registerController(node, newCos);

	float frequency;
	stringstream ss;
	ss.str(node->Attribute("frequency"));
	ss>>frequency;
	ss.clear();

	float amplitude;
	ss.str(node->Attribute("amplitude"));
	ss>>amplitude;
	ss.clear();

	float offset;
	ss.str(node->Attribute("offset"));
	ss>>offset;

	bool positive=true;
	if(node->Attribute("sign")=="-")
		positive=false;

	newCos->amplitude=amplitude;
	newCos->frequency=frequency;
	newCos->offset=offset;
	newCos->positive=positive;

	list<Element> time=node->Children();
	list<Element>::iterator t=time.begin();

	if((*t).Attribute("connectFrom")=="0")
		newCos->time.connectFrom(m_time);
	else
	{
		void* controller = getController((*t).Attribute("connectFrom"));
		if(controller==0)
			return false;
		newCos->time.connectFrom((tsg::Source<float>*)controller);
	}

	return true;
}

bool CXml::addSinus(Element* node)
{
	if(node->Name()!="sinus")
		return false;

	calculTrajectorySin* newSin = new calculTrajectorySin();
	registerController(node, newSin);

	float frequency;
	stringstream ss;
	ss.str(node->Attribute("frequency"));
	ss>>frequency;
	ss.clear();

	float amplitude;
	ss.str(node->Attribute("amplitude"));
	ss>>amplitude;
	ss.clear();

	float offset;
	ss.str(node->Attribute("offset"));
	ss>>offset;

	bool positive=true;
	if(node->Attribute("sign")=="-")
		positive=false;

	newSin->amplitude=amplitude;
	newSin->frequency=frequency;
	newSin->offset=offset;
	newSin->positive=positive;

	list<Element> time=node->Children();
	list<Element>::iterator t=time.begin();

	if((*t).Attribute("connectFrom")=="0")
		newSin->time.connectFrom(m_time);
	else
	{
		void* controller = getController((*t).Attribute("connectFrom"));
		if(controller==0)
			return false;
		newSin->time.connectFrom((tsg::Source<float>*)controller);
	}

	return true;
}

bool CXml::addTerrain(Element* node, Group* root)
{
	if(node->Name()!="terrain")
		return false;

	CTerrain* newTerrain = new CTerrain();

	float size;
	stringstream ss;
	ss.str(node->Attribute("size"));
	ss>>size;
	newTerrain->m_size=size;

	root->addChild(newTerrain);

	return true;
}
bool CXml::addCanon(Element* node, Group* root)
{
	if(node->Name()!="canon")
		return false;

	CCanon* canon = new CCanon();
	if(node->Attribute("connectFrom")=="0")
	{
		float angle;
		stringstream ss;
		ss.str(node->Attribute("angle"));
		ss>>angle;
		canon->m_angleCanon=angle;
	}
	else
	{
		void* controller = getController(node->Attribute("connectFrom"));
		canon->m_angleCanon.connectFrom((tsg::Source<float>*)controller);
	}
	root->addChild(canon);
	return true;
}

bool CXml::addAwesomeAttraction(Element* node, Group* root)
{
	if(node->Name()!="awesomeAttraction")
		return false;

	float size;
	stringstream ss;
	ss.str(node->Attribute("size"));
	ss>>size;

	CAwesomeAttraction* newAttraction = new CAwesomeAttraction();
	newAttraction->m_size=size;

	list<Element> listRotation=node->Children();
	list<Element>::iterator rotation=listRotation.begin();

	if((*rotation).Attribute("connectFrom")=="0")
	{
		float rotationPillar;
		ss.str(rotation->Content());
		ss>>rotationPillar;
		newAttraction->m_rotationPillar=rotationPillar;
	}
	else
	{
		void* controller=getController(rotation->Attribute("connectFrom"));
		newAttraction->m_rotationPillar.connectFrom((tsg::Source<float>*)controller);
	}
	rotation++;
	if((*rotation).Attribute("connectFrom")=="0")
	{
		float rotationArm;
		ss.str(rotation->Content());
		ss>>rotationArm;
		newAttraction->m_rotationArm=rotationArm;
	}
	else
	{
		void* controller=getController(rotation->Attribute("connectFrom"));
		newAttraction->m_rotationArm.connectFrom((tsg::Source<float>*)controller);
	}
	rotation++;
	if((*rotation).Attribute("connectFrom")=="0")
	{
		float rotationBooth;
		ss.str(rotation->Content());
		ss>>rotationBooth;
		newAttraction->m_rotationBooth=rotationBooth;
	}
	else
	{
		void* controller=getController(rotation->Attribute("connectFrom"));
		newAttraction->m_rotationBooth.connectFrom((tsg::Source<float>*)controller);
	}
	root->addChild(newAttraction);
	return true;
}

bool CXml::addPillar(Element* node, Group* root)
{
	if(node->Name()!="pillar")
		return false;

	CPillar* newPillar = new CPillar();
	stringstream ss;
	ss.str(node->Attribute("height"));
	float height;
	ss>>height;
	ss.clear();
	ss.str(node->Attribute("thickness"));
	float thickness;
	ss>>thickness;
	newPillar->m_height=height;
	newPillar->m_thickness=thickness;
	root->addChild(newPillar);
	return true;
}

bool CXml::addGreatWheel(Element* node, Group* root)
{
	if(node->Name()!="greatWheel")
		return false;

	list<Element> childWheel=node->Children();
	list<Element>::iterator i=childWheel.begin();
	
	stringstream ss;
	ss.str(i->Content());
	float size;
	ss>>size;

	i++;
	void* controllerRotationBooth=getController(i->Attribute("connectFrom"));
	if(controllerRotationBooth==0)
		return false;

	i++;
	void* controllerRotationWheel=getController(i->Attribute("connectFrom"));
	if(controllerRotationWheel==0)
		return false;

	//create the wheel
	Rotate* rotateWheel = new Rotate();
	rotateWheel->axis=Vector3(0, 0, 1);
	rotateWheel->angle.connectFrom((tsg::Source<float>*)controllerRotationWheel);
	root->addChild(rotateWheel);
	root->addChild(new Cube(size*15));

	//create the booth
	Rotate* rotateBooth = new Rotate();
	rotateBooth->axis=Vector3(0, 0, 1);
	rotateBooth->angle.connectFrom((tsg::Source<float>*)controllerRotationBooth);

	Separator* booth = new Separator();
	booth->addChild(new Translate(15*size, 0, 0));
	booth->addChild(rotateBooth);
	booth->addChild(new Cube(size*3));
	root->addChild(booth);
	booth = new Separator();
	booth->addChild(new Translate(-15*size, 0, 0));
	booth->addChild(rotateBooth);
	booth->addChild(new Cube(size*3));
	root->addChild(booth);
	booth = new Separator();
	booth->addChild(new Translate(0, 15*size, 0));
	booth->addChild(rotateBooth);
	booth->addChild(new Cube(size*3));
	root->addChild(booth);
	booth = new Separator();
	booth->addChild(new Translate(0, -15*size, 0));
	booth->addChild(rotateBooth);
	booth->addChild(new Cube(size*3));
	root->addChild(booth);
	booth = new Separator();
	booth->addChild(new Translate(13*size, 13*size, 0));
	booth->addChild(rotateBooth);
	booth->addChild(new Cube(size*3));
	root->addChild(booth);
	booth = new Separator();
	booth->addChild(new Translate(-13*size, -13*size, 0));
	booth->addChild(rotateBooth);
	booth->addChild(new Cube(size*3));
	root->addChild(booth);
	booth = new Separator();
	booth->addChild(new Translate(13*size, -13*size, 0));
	booth->addChild(rotateBooth);
	booth->addChild(new Cube(size*3));
	root->addChild(booth);
	booth = new Separator();
	booth->addChild(new Translate(-13*size, 13*size, 0));
	booth->addChild(rotateBooth);
	booth->addChild(new Cube(size*3));
	root->addChild(booth);
	
	return true;

}

bool CXml::addCarousel(Element* node, Group* root)
{
	if(node->Name()!="carousel")
		return false;

	list<Element> carouselAttribute=node->Children();
	list<Element>::iterator i=carouselAttribute.begin();
	stringstream ss;
	ss.str(i->Content());
	float size;
	ss>>size;
	CCarousel* newCarousel = new CCarousel(size);

	i++;
	if(i->Attribute("connectFrom")=="0")
	{
		ss.clear();
		ss.str(i->Content());
		float rotation;
		ss>>rotation;
		newCarousel->m_rotationAngle=rotation;
	}
	else
	{
		void* controller=getController(i->Attribute("connectFrom"));
		if(controller==0)
			return false;

		newCarousel->m_rotationAngle.connectFrom((tsg::Source<float>*)controller); 
	}

	i++;
	ss.clear();
	ss.str(i->Attribute("amplitude"));
	float amplitude;
	ss>>amplitude;

	ss.clear();
	ss.str(i->Attribute("frequency"));
	float frequency;
	ss>>frequency;

	ss.clear();
	ss.str(i->Attribute("offset"));
	float offset;
	ss>>offset;

	COscillator* arrayOscillator[8];
	for(int i=0; i<8; i++)
	{
		CTimeController* timeController = new CTimeController();
		timeController->m_applicationTime.connectFrom(m_time);
		timeController->m_startTime=1*(i+1);
		timeController->m_endTime=-1;
		COscillator* newOscillator= new COscillator(amplitude, frequency, offset);
		newOscillator->m_time.connectFrom(timeController);
		arrayOscillator[i]=newOscillator;
	}
	newCarousel->m_upAndDown1.connectFrom(arrayOscillator[0]);
	newCarousel->m_upAndDown2.connectFrom(arrayOscillator[1]);
	newCarousel->m_upAndDown3.connectFrom(arrayOscillator[2]);
	newCarousel->m_upAndDown4.connectFrom(arrayOscillator[3]);
	newCarousel->m_upAndDown5.connectFrom(arrayOscillator[4]);
	newCarousel->m_upAndDown6.connectFrom(arrayOscillator[5]);
	newCarousel->m_upAndDown7.connectFrom(arrayOscillator[6]);
	newCarousel->m_upAndDown8.connectFrom(arrayOscillator[7]);

	root->addChild(newCarousel);
	return true;
		
}

int CXml::convertNameToInt(Element* node)
{
	if(node->Name()=="camera")
		return CXml::eTypeCamera;
	else if(node->Name()=="lookAt")
		return CXml::eTypeLookAt;
	else if(node->Name()=="bezier3Curve")
		return CXml::eTypeBezier3Curve;
	else if(node->Name()=="bezierPath")
		return CXml::eTypeBezierPath;
	else if(node->Name()=="applicationTime")
		return CXml::eTypeApplicationTime;
	else if(node->Name()=="particleSystem")
		return CXml::eTypeParticleSystem;
	else if(node->Name()=="separator")
		return CXml::eTypeSeparator;
	else if(node->Name()=="material")
		return CXml::eTypeMaterial;
	else if(node->Name()=="cube")
		return CXml::eTypeCube;
	else if(node->Name()=="translate")
		return CXml::eTypeTranslate;
	else if(node->Name()=="rotate")
		return CXml::eTypeRotate;
	else if(node->Name()=="timeController")
		return CXml::eTypeTimeController;
	else if(node->Name()=="linearFunction")
		return CXml::eTypeLinearFunction;
	else if(node->Name()=="constantFloat")
		return CXml::eTypeConstantFloat;
	else if(node->Name()=="putInVector3")
		return CXml::eTypePutInVector3;
	else if(node->Name()=="kinetic")
		return CXml::eTypeKinetic;
	else if(node->Name()=="keyframe")
		return CXml::eTypeKeyframe;
	else if(node->Name()=="bezierCoordinates")
		return CXml::eTypeBezierCoordinates;
	else if(node->Name()=="cosinus")
		return CXml::eTypeCosinus;
	else if(node->Name()=="sinus")
		return CXml::eTypeSinus;
	else if(node->Name()=="terrain")
		return CXml::eTypeTerrain;
	else if(node->Name()=="canon")
		return CXml::eTypeCanon;
	else if(node->Name()=="awesomeAttraction")
		return CXml::eTypeAwesomeAttraction;
	else if(node->Name()=="pillar")
		return CXml::eTypePillar;
	else if(node->Name()=="greatWheel")
		return CXml::eTypeGreatWheel;
	else if(node->Name()=="carousel")
		return CXml::eTypeCarousel;
	else
		return CXml::eTypeUnknown;
}

void* CXml::getController(string connectFrom)
{
	vector<connectController>::iterator i=m_vectorController.begin();

	while(i!=m_vectorController.end())
	{
		if((*i).m_nameOfController!=connectFrom)
			i++;
		else
			return (*i).m_pointerToController;
	}
	return 0;
}

void CXml::registerController(Element* node, void* controller)
{
	connectController c;
	c.m_nameOfController=node->Attribute("name");
	c.m_pointerToController=controller;
	m_vectorController.push_back(c);
}